package com.MetroMinder.Utilities;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;


public class UrlHelpers {
	
	/* {@link StatusLine} HTTP status code when no server error has occurred.  */
    private static final int HTTP_STATUS_OK = 200;
    
    /* Shared buffer used by {@link #getUrlContent(String)} when reading results
     * from an API request. */
    private static byte[] sBuffer = new byte[512];

    /* Thrown when there were problems contacting the remote API server, either
     * because of a network error, or the server returned a bad status code. */
    public static class ApiException extends Exception
    {        
    	public ApiException(String detailMessage, Throwable throwable)
    	{
            super(detailMessage, throwable);
        }

        public ApiException(String detailMessage)
        {
            super(detailMessage);
        }        
    }
    

    /* Thrown when there were problems parsing the response to an API call,
     * either because the response was empty, or it was malformed.  */
    public static class ParseException extends Exception 
    {    	
        public ParseException(String detailMessage, Throwable throwable) 
        {
            super(detailMessage, throwable);
        }        
    }

    /* Read and return the full HTML content of the URL requested
     * @param urlToFetch 
     * @return Exact content of page.
     * @throws ApiException If any connection or server error occurs.
     * @throws ParseException If there are problems parsing the response. */
    public static String getPageContent(String urlToFetch) throws ApiException, ParseException 
    {
    	return getUrlContent(String.format(urlToFetch));
    }
    

    /* Pull the raw text content of the given URL. This call blocks until the
     * operation has completed, and is synchronized because it uses a shared
     * buffer {@link #sBuffer}.
     * @param url The exact URL to request.
     * @return The raw content returned by the server.
     * @throws ApiException If any connection or server error occurs. */
    protected static synchronized String getUrlContent(String url) throws ApiException 
    {
        // Create client and set our specific user-agent string
        HttpClient client = new DefaultHttpClient();
        HttpGet request = new HttpGet(url);
        request.setHeader("User-Agent", "MetroMinder (Linux; Android)");

        try
        {
            HttpResponse response = client.execute(request);

            // Check if server response is valid
            StatusLine status = response.getStatusLine();
            
            if (status.getStatusCode() != HTTP_STATUS_OK) 
            {
                throw new ApiException("Invalid response from server: " + status.toString());
            }

            // Pull content stream from response
            HttpEntity entity = response.getEntity();
            InputStream inputStream = entity.getContent();

            ByteArrayOutputStream content = new ByteArrayOutputStream();

            // Read response into a buffered stream
            int readBytes = 0;
            while ((readBytes = inputStream.read(sBuffer)) != -1) 
            {
                content.write(sBuffer, 0, readBytes);
            }

            // Return result from buffered stream
            return new String(content.toByteArray());
        } 
        catch (IOException e) 
        {
            throw new ApiException("Problem communicating with API", e);
        }
    	
    }

}
